﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using System.Collections;
using System.Data.SqlClient;
namespace Persistencia
{
    public abstract class TransaccionBase : IDisposable
    {
        
        private SqlConnection conn;
        private string nombre;

        protected Hashtable factorias = new Hashtable();

        abstract internal SqlTransaction SQLTran { get; }
        public virtual SqlConnection Conexion
        {
            get
            {
                if (conn != null && conn.State==System.Data.ConnectionState.Open)
                    return conn;

                conn = new SqlConnection(ConfigLoader.getString("ConnectionString"));
                conn.Open();

                return conn;

            }
        }

        internal TransaccionBase(string nombre)
        {
            this.nombre = nombre;
        }

        public void EjecutarComandoSinRespuesta(SqlCommand comm)
        {
            if (comm.Connection == null)
                comm.Connection = this.Conexion;
            comm.ExecuteNonQuery();
        }

        public T Factoria<T>() where T:Factoria
        {
            if (!factorias.ContainsKey(typeof(T).Name))
            {
                Type t = typeof(T);
                
                ConstructorInfo ci= t.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance ,null,new Type[] {this.GetType().BaseType},null);
                object o=ci.Invoke(new object[]{this});
                factorias.Add(t.Name, o);
            }

            return (T)factorias[typeof(T).Name];
        }

        public virtual List<HashTableNCSensitive> EjecutarComando(SqlCommand comm,int cantidad)
        {
            if (comm.Connection == null)
                comm.Connection = this.Conexion;
            
            List<HashTableNCSensitive> rs = new List<HashTableNCSensitive>();
            SqlDataReader dr= comm.ExecuteReader();
            try
            {

                string[] claves = new string[dr.FieldCount];
                int i = 0;
                while (i < dr.FieldCount)
                {
                    claves[i] = dr.GetName(i);
                    i++;
                }

                i = 0;
                while (dr.Read() && (cantidad == 0 || i < cantidad))
                {

                    object[] objs = new object[dr.FieldCount];
                    dr.GetValues(objs);

                    rs.Add(new HashTableNCSensitive(claves, objs));
                    i++;
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                dr.Close();
            }

            return rs;
        }

        public virtual string Nombre 
        {
            get
            {
                return nombre;
            }

        }

        public virtual void Cerrar()
        {
            if(this.conn!=null)
                this.conn.Close();
        }

        public void Dispose()
        {
            this.Cerrar();
        }
    }
}
